﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using CommLib.LeCloud.Models;

namespace CommLib.LeCloud
{
    public class LeCloudLive
    {
        private const string BaseUrl = "http://api.open.letvcloud.com/live/execute?";
        private const string Ver = "3.0";
        private const string MethodSearch = "letv.cloudlive.activity.search";
        private const string MethodCreate = "letv.cloudlive.activity.create";
        private const string MethodEdit = "letv.cloudlive.activity.modify";
        private const string MethodPushUrl = "letv.cloudlive.activity.getPushUrl";
        private const string MethodPlayUrl = "letv.cloudlive.activity.playerpage.getUrl";
        private const string MethodGetToken = "letv.cloudlive.activity.getPushToken";
        private readonly int _userid;
        private readonly string _appkey;
        public LeCloudLive(int userid,string appkey)
        {
            _userid = userid;
            _appkey = appkey;
        }

        /// <summary>
        /// 查询活动接口首页
        /// </summary>
        /// <param name="activityId">直播活动ID</param>
        /// <returns>ResultModels{Code,Message}</returns>
        public async Task<ResultModels> Search(string activityId) => await LeCloudMothodGet(MethodSearch, activityId);

        /// <summary>
        /// 创建活动
        /// </summary>
        /// <param name="model"></param>
        /// <returns>ResultModels{Code,Message}</returns>
        public async Task<ResultModels> Create(LiveCreateModels model)
        {
            var param = GetBaseParam(MethodCreate);
            var p1 = ObjectIterator(model);
            var dictionary = param.Union(p1).ToDictionary(a=>a.Key,b=>b.Value);
            dictionary.Add("sign", GetSign(dictionary));
            var data = dictionary.Select(p => new KeyValuePair<string, string>(p.Key, p.Value)).ToList();
            var form = new FormUrlEncodedContent(data);
            ResultModels result;
            using (var client = new HttpClient())
            {
                var response = await client.PostAsync(BaseUrl, form);
                result = await HttpResult(response);
            }
            return result;
        }

        /// <summary>
        /// 修改活动
        /// </summary>
        /// <param name="model"></param>
        /// <returns>ResultModels{Code,Message}</returns>
        public async Task<ResultModels> Edit(LiveEditModels model)
        {
            if (string.IsNullOrEmpty(model.activityId))
                return new ResultModels {Code = -2, Message = "activityId不能为空"};
            var param = GetBaseParam(MethodEdit);
            var p1 = ObjectIterator(model);
            var dictionary = param.Union(p1).ToDictionary(a => a.Key, b => b.Value);
            dictionary.Add("sign", GetSign(dictionary));
            var data = dictionary.Select(p => new KeyValuePair<string, string>(p.Key, p.Value)).ToList();
            var form = new FormUrlEncodedContent(data);
            ResultModels result;
            using (var client = new HttpClient())
            {
                var response = await client.PostAsync(BaseUrl, form);
                result = await HttpResult(response);
            }
            return result;
        }

        /// <summary>
        /// 获取直播推流地址接口首页
        /// </summary>
        /// <param name="activityId">直播活动ID</param>
        /// <returns></returns>
        public async Task<ResultModels> GetPushUrl(string activityId) => await LeCloudMothodGet(MethodPushUrl, activityId);
       
        /// <summary>
        /// 获取播放地址
        /// </summary>
        /// <param name="activityId">直播活动ID</param>
        /// <returns></returns>
        public async Task<ResultModels> GetPlayUrl(string activityId) => await LeCloudMothodGet(MethodPlayUrl, activityId);
    
        /// <summary>
        /// 获取推流token接口
        /// </summary>
        /// <param name="activityId">直播活动ID</param>
        /// <returns></returns>
        public async Task<ResultModels> GetToken(string activityId) => await LeCloudMothodGet(MethodGetToken, activityId);
        
        private async Task<ResultModels> LeCloudMothodGet(string method,string activityId)
        {
            if (string.IsNullOrEmpty(activityId) || string.IsNullOrEmpty(_appkey))
                return new ResultModels {Code = -2, Message = "activityId或appkey不能为空"};
            var param = GetBaseParam(method);
            param.Add("activityId", activityId);
            var url = BaseUrl + Web.StringToUrlParam.ToQueryString(param) + "&sign=" + GetSign(param);
            ResultModels result;
            using (var client = new HttpClient())
            {
                var response = await client.GetAsync(url);
                result = await HttpResult(response);
            }
            return result;
        }

        private string GetSign(Dictionary<string, string> param)
        {
            var keyValuePairs = param.OrderBy(x => x.Key);
            var keyStr = "";
            keyValuePairs.ToList().ForEach(x =>
            {
                keyStr += x.Key + x.Value;
            });
            keyStr += _appkey;
            var key = Security.Md5Encrypt.GetMd5Hash(keyStr);
            return key;
        }

        private static async Task<ResultModels> HttpResult(HttpResponseMessage response)
        {
            var result = new ResultModels();
            if (response.IsSuccessStatusCode)
            {
                response.EnsureSuccessStatusCode();
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    result.Code = 200;
                    result.Message = await response.Content.ReadAsStringAsync();
                }
            }
            else
            {
                if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
                {
                    result.Code = (int)response.StatusCode;
                    result.Message = await response.Content.ReadAsStringAsync();
                }
                else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                {
                    result.Code = (int)response.StatusCode;
                    result.Message = await response.Content.ReadAsStringAsync();
                }
                else if (response.StatusCode == System.Net.HttpStatusCode.Moved)
                {
                    result.Code = (int)response.StatusCode;
                    result.Message = "数据没有发生变化，客户端缓存有效";
                }
                else
                {
                    result.Code = -1;
                    result.Message = "未知错误";
                }
            }
            return result;
        }

        private static Dictionary<string, string> ObjectIterator<T>(T type)
        {
            Dictionary<string, string> param = new Dictionary<string, string>();
            foreach (var p in type.GetType().GetProperties())
            {
                var value = p.GetValue(type);
                if (value != null)
                {
                    var t = value.GetType();
                    if (t != typeof (string))
                    {
                        if (t == typeof (CodeRateTypes[]))
                        {
                            var orderedEnumerable = ((int[]) value).Distinct().OrderBy(i => i);
                            value = string.Join(",", orderedEnumerable);
                        }
                        else
                        {
                            value = (int) value;
                        }
                    }

                }
                param.Add(p.Name, value?.ToString());
            }
            return param;
        }

        private Dictionary<string, string> GetBaseParam(string method) 
            =>  new Dictionary<string, string>
                {
                    {"method", method},
                    {"ver", Ver},
                    {"userid", _userid.ToString()},
                    {"timestamp", Currenttimemillis().ToString()}
                };
        private static long Currenttimemillis()=> (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
    }


}
